#include "PixelImage.h"

using namespace std;

PixelImage::PixelImage(char * fileName)
{
  ifstream sampleImage(fileName);
  string lineInput;
  int loopCount;

  /* Initializations */
  pixelAddressCounter = 0;
  currentXPosition = 0;
  currentYPosition = 0;

  if(!sampleImage)
  {
    cout << "File Could Not Be Opened" << endl;
  }
  else
  {
    //Get PNM File Type
    sampleImage >> lineInput;

    // Detect Correct PNM File
    if(lineInput.at(1) == '1')
    {
      cout << "Binary PNM File Found" << endl << endl;
      // Get Junk Data from the line
      getline(sampleImage, lineInput);

      // Get Author Information (Easiest Way)
      getline(sampleImage, lineInput);
      cout << lineInput << endl << endl;

      // Get Size Information
      sampleImage >> height;
      sampleImage >> width;
      InitializePixelMatrix();
      
      LoadImageIntoMatrix(&sampleImage);
      
      PrintPixelImage();
    }
    else
    {
      cout << "This File Format is not Supported" << endl;
    }
  }
}

void PixelImage::LoadImageIntoMatrix(ifstream * pixelFile)
{
  int loopCount;
  string lineInput;

  while(*pixelFile)
  {
    *pixelFile >> lineInput;
    for(loopCount = 0 ; loopCount < lineInput.length() ; loopCount++ )
    {
      std::cout << lineInput.at(loopCount) << " ";
      currentPixel = ('1' == lineInput.at(loopCount));
      InsertPixel();
      if(!IncrementToNextPixelPosition())
      {
        while(*pixelFile) *pixelFile >> lineInput;
        break;
      }
    }
  }
}

void PixelImage::InsertPixel(void)
{
  PixelMatrix[currentXPosition][currentYPosition].SetPixelValue(currentPixel);
  PixelMatrix[currentXPosition][currentYPosition].SetPixelPosition(currentXPosition, currentYPosition);
  PixelMatrix[currentXPosition][currentYPosition].SetPixelAddress(pixelAddressCounter++);

  if( currentXPosition > 0 )
  {
    /* Set West Pixel Ptr */
    PixelMatrix[currentXPosition][currentYPosition].SetWestPixelObj(&PixelMatrix[currentXPosition - 1][currentYPosition]);
    /* Set West's East Pixel Ptr to Self */
    PixelMatrix[currentXPosition - 1][currentYPosition].SetEastPixelObj(&PixelMatrix[currentXPosition][currentYPosition]);
  }

  /* Check For Existence of Upper Pixels */
  if( currentYPosition > 0 )
  {

    /* Set North Pixel Ptr */
    PixelMatrix[currentXPosition][currentYPosition].SetNorthPixelObj(&PixelMatrix[currentXPosition][currentYPosition - 1]);
    /* Set North's South Pixel Ptr to Self */
    PixelMatrix[currentXPosition][currentYPosition - 1].SetSouthPixelObj(&PixelMatrix[currentXPosition][currentYPosition]);
    
    if( currentXPosition > 0 )
    {
      /* Set North West Pixel Ptr */
      PixelMatrix[currentXPosition][currentYPosition].SetNorthWestPixelObj(&PixelMatrix[currentXPosition - 1 ][currentYPosition - 1]);
      /* Set North West's South East Pixel Ptr to Self */
      PixelMatrix[currentXPosition - 1][currentYPosition - 1].SetSouthEastPixelObj(&PixelMatrix[currentXPosition][currentYPosition]);
    }
  }

  /* Check for Existence of North East Pixel */
  if( ( currentXPosition < ( width - 1 ) ) && ( currentYPosition > 0 ) )
  {
    /* Set North East Pixel Ptr */
    PixelMatrix[currentXPosition][currentYPosition].SetNorthEastPixelObj(&PixelMatrix[currentXPosition + 1][currentYPosition - 1]);
    /* Set North East's South West Pixel Ptr to Self */
    PixelMatrix[currentXPosition + 1][currentYPosition - 1].SetSouthWestPixelObj(&PixelMatrix[currentXPosition][currentYPosition]);
  }
}

bool PixelImage::IncrementToNextPixelPosition(void)
{
  if(currentYPosition == (height - 1))
  {
    if(currentXPosition == (width - 1))
    {
      return 0;
    }
    currentYPosition = 0;
    currentXPosition++;
  }
  else
  {
    std::cout << std::endl;
    currentYPosition++;
  }
  return 1;
}

void PixelImage::InitializePixelMatrix(void)
{
  int loop;

  PixelMatrix = new PixelProcessor*[height];
  for( loop = 0 ; loop < height ; loop++ )
  {
    PixelMatrix[loop] = new PixelProcessor[width];
  }
}

PixelImage::~PixelImage(void)
{
  int loop;

  for( loop = 0 ; loop < height ; loop++ )
  {
    delete [] PixelMatrix[loop];
  }

  delete PixelMatrix;
}

void PixelImage::PrintPixelImage(void)
{
  int x, y;
  char tmp;

  for( x = 0; x < width ; x++)
  {
    for( y = 0; y < height ; y++)
    {
      if(0 == PixelMatrix[x][y].GetPixelValue())
      {
        cout << ".";
      }
      else
      { 
        cout << "+";
      }
      cout << " ";
    }
    cout << endl;
  }
}
